package com.dlc.felear.xiaoensale.dlc_serial_port;

import android.serialport.SerialPort;
import android.text.TextUtils;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.utils.HexUtil;
import com.dlc.felear.xiaoensale.utils.MyLog;

import org.simple.eventbus.EventBus;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 数据传输实现类
 * Created by felear on 2018/8/4.
 */

public class SerialPortControl {
    private static final String TAG = "SerialPortControl";
//    private static final String SOPRTNO = "/dev/ttyS3";
    // 管理串口类
    private static HashMap<String, SerialPort> serialPortMap = new HashMap<>();
    // 指令集同步队列
    private static HashMap<String, ArrayBlockingQueue<byte[]>> mOrderQueue = new HashMap();
    private static HashMap<String, ReceiverRunnable> mapReceiverRunnable = new HashMap();
    private static HashMap<String, SendRunnable> mapSendRunnable = new HashMap();

    /**
     * 添加硬件传输通道
     *
     * @param port
     * @param baudRate
     */
    static void addSerialPort(String port, int baudRate, String event, int waitDelay) {
        SerialPort serialPort = serialPortMap.get(port);
        if (serialPort != null) {
            Log.e(TAG, "port=" + port + " 已添加");
            return;
        }

        ArrayBlockingQueue<byte[]> queue = mOrderQueue.get(port);
        if (queue == null) {
            mOrderQueue.put(port, new ArrayBlockingQueue<byte[]>(100));
        }
        try {
            serialPort = new SerialPort(new File(port), baudRate, 0);
            serialPortMap.put(port, serialPort);
            new ReceiverRunnable(serialPort.getInputStream(), event).start();
            new SendRunnable(serialPort.getOutputStream(), port, event, waitDelay).start();
        } catch (Exception e) {
            Log.e(TAG, "port=" + port + " " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void clearCmdData(String port) {
        ArrayBlockingQueue<byte[]> queue = mOrderQueue.get(port);
        if (queue != null) {
            queue.clear();
        }
    }

    public static void sendData(String port, byte[] orders) {
        ArrayBlockingQueue<byte[]> queue = mOrderQueue.get(port);
        if (queue == null) {
            MyLog.e(TAG, "未添加连接" + "port=" + port);
            return;
        }
        queue.offer(orders);
//        Log.e(TAG, "port=" + port + " cmdSize=" + queue.size());
    }

    // 接受数据线程
    static class ReceiverRunnable extends Thread {

        private String event;
        private InputStream inputStream;

        public ReceiverRunnable(InputStream inputStream, String event) {
            this.event = event;
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            try {
                while (!isInterrupted()) {
                    if (inputStream == null) {
                        return;
                    }
                    // 最终指令存储位置
                    byte[] readBuf = new byte[512];
                    byte[] orders = null;
                    int length = 0;
                    while ((length = inputStream.read(readBuf)) > 0) {
                        orders = new byte[length];
                        System.arraycopy(readBuf, 0, orders, 0, length);
                        if (length > 0) {
//                            if (TextUtils.equals(SOPRTNO, event)) {
                                Log.e(TAG, event + " __ " + HexUtil.bytes2HexString(orders));
//                            }
                            EventBus.getDefault().post(orders, event);
                        }
                        Thread.sleep(50);
                    }
                }
            } catch (Exception e) {
                run();
            }

        }
    }


    // 发送数据线程
    static class SendRunnable extends Thread {
        private final ArrayBlockingQueue<byte[]> mQueue;
        private OutputStream outputStream;
        private String port;
        private String event;
        private int waitDelay = 80;

        public SendRunnable(OutputStream outputStream, String port, String event, int waitDelay) {
            this.event = event;
            this.port = port;
            this.waitDelay = waitDelay;
            this.outputStream = outputStream;
            mQueue = mOrderQueue.get(port);
        }

        @Override
        public void run() {
            try {
                byte[] orders = null;
                // take位阻塞方法，取不到消息时会阻塞当前线程
                while ((orders = mQueue.take()) != null) {
//                    if (TextUtils.equals(port,SOPRTNO)) {
                        Log.e(TAG,  " 串口号：" + port + "  指令" + HexUtil.bytes2HexString(orders) + " size=" + mQueue.size());
//                    }
                    // 发送普通指令
                    outputStream.write(orders);
                    // 睡眠，防止数据粘包
                    Thread.sleep(waitDelay);
                }
            } catch (Exception e) {
                run();
            }
        }
    }
}
